﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using System.Web.Security;
using VideoSeller.Business.Data;
using VideoSeller.Business.Data.Enums;
using VideoSeller.Business.Models;
using VideoSeller.Core.Web.ActionResults;
using VideoSeller.Web.Models;

namespace VideoSeller.Web.Controllers
{
	[Authorize(Roles = "Administrator, Moderator, Reports")]
	public class AdminController : BaseController
	{
		private readonly ResourceModel _resourceModel;
		private readonly ClientModel _clientModel;
		private readonly MembershipUserModel _membershipUserModel;
		private readonly FinanceModel _financeModel;
		private readonly PostingModel _postingModel;
		private readonly OnlineContentModel _onlineContentModel;
		private readonly SettingsModel _settingsModel;
		private readonly ContentModel _contentModel;

		public AdminController(ResourceModel resourceModel, ClientModel clientModel, MembershipUserModel membershipUserModel, FinanceModel financeModel, PostingModel postingModel, OnlineContentModel onlineContentModel, SettingsModel settingsModel, ContentModel contentModel)
		{
			_resourceModel = resourceModel;
			_clientModel = clientModel;
			_membershipUserModel = membershipUserModel;
			_financeModel = financeModel;
			_postingModel = postingModel;
			_onlineContentModel = onlineContentModel;
			_settingsModel = settingsModel;
			_contentModel = contentModel;
		}

		[HttpGet]
		[Authorize(Roles = "Administrator, Moderator, Reports")]
		public ActionResult Index()
		{
			if (Roles.IsUserInRole("Reports"))
			{
				return RedirectToAction("FundsReport");
			}

			return RedirectToAction("Clients");
		}

		[HttpGet]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult Settings()
		{
			return View(_settingsModel.GetAll().OrderBy(x => x.Id));
		}

		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult Content(ContentPlaceType? contentPlace)
		{
			var model = new AdminContentViewModel();

			if (contentPlace.HasValue)
			{
				model.ContentPlace = contentPlace;
				model.Items = _contentModel.GetAll().Where(x => x.ContentPlace.KeyName == contentPlace.Value.ToString()).ToList();
			}
			else
			{
				model.Items = _contentModel.GetAll().ToList();
			}

			return View(model);
		}

		[HttpGet]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult CreateContent()
		{
			var model = new ManageContentViewModel();
			return View("ManageContent", model);
		}

		[HttpGet]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult EditContent(int id)
		{
			var model = new ManageContentViewModel {Content = _contentModel.GetContent(id)};
			return View("ManageContent", model);
		}

		[HttpPost]
		[ValidateInput(false)]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult UpdateContent(ManageContentViewModel model)
		{
			_contentModel.SaveContent(model.Content);
			return RedirectToAction("Content");
		}

		[HttpDelete]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult DeleteContentItem(int id)
		{
			_contentModel.DeleteContent(id);
			return RedirectToAction("Content");
		}

		[HttpGet]
		[Authorize(Roles = "Administrator, Moderator")]
		public ViewResult Resources()
		{
			var model = new ResourcesViewModel
				{
					Cultures = _resourceModel.GetUniqueCultures().ToList(),
					Items = _resourceModel.GetResourceItems()
				};
			return View(model);
		}

		[HttpGet]
		[Authorize(Roles = "Administrator, Moderator")]
		public ViewResult Clients(string loginFilter)
		{
			var model = new ClientsViewModel();

			if (string.IsNullOrEmpty(loginFilter))
			{
				model.Clients = _clientModel.GetAll();
			}
			else
			{
				var user = _membershipUserModel.GetMembershipUser(loginFilter);
				model.Clients = new List<Client>();

				if (user != null)
				{
					model.Clients = new List<Client> {user.Client};
					model.LoginFilter = loginFilter;
				}
			}

			return View(model);
		}

		[HttpGet]
		[Authorize(Roles = "Administrator, Moderator")]
		public ViewResult Finance(string loginFilter, int? page)
		{
			var model = new ClientsViewModel
				{
					FilterViewModel = new ContentListFilterViewModel
						{
							Action = "Finance",
							Controller = "Admin",
							PageNumber = page.HasValue ? page.Value : 1,
							PageSize = 50
						}
				};

			if (string.IsNullOrEmpty(loginFilter))
			{
				model.Clients = _clientModel.GetAll();

				var total = model.Clients.Count();
				var skip = (model.FilterViewModel.PageNumber - 1) * model.FilterViewModel.PageSize;

				if (skip > total)
				{
					skip = 0;
				}

				model.Clients = model.Clients.Skip(skip).Take(model.FilterViewModel.PageSize);
				var pageCount = total / model.FilterViewModel.PageSize;

				if (total % model.FilterViewModel.PageSize != 0)
				{
					pageCount = pageCount + 1;
				}

				model.FilterViewModel.PageCount = pageCount;
				model.FilterViewModel.Total = total;
			}
			else
			{
				var user = _membershipUserModel.GetMembershipUser(loginFilter);
				model.Clients = new List<Client>();

				if (user != null)
				{
					model.Clients = new List<Client> { user.Client };
					model.LoginFilter = loginFilter;
				}
			}

			return View(model);
		}

		[HttpGet]
		[Authorize(Roles = "Administrator, Moderator")]
		public ViewResult Withdraw(string loginFilter)
		{
			var model = new AdminWithdrawViewModel {Items = _postingModel.GetAll().Where(x => x.WithdrawType.HasValue)};

			if (!string.IsNullOrEmpty(loginFilter))
			{
				var user = _membershipUserModel.GetMembershipUser(loginFilter);
				model.Items = new List<Posting>();

				if (user != null)
				{
					model.Items = _postingModel.GetAll().Where(x => x.WithdrawType.HasValue && x.FinanceId == user.UserId);
					model.LoginFilter = loginFilter;
				}
			}

			return View(model);
		}

		[HttpGet]
		[Authorize(Roles = "Administrator, Moderator")]
		public ViewResult Online(string loginFilter, SortDirection? time, SortDirection? views, SortDirection? claims, int? page)
		{
			var model = GetAdminViewModel(OnlineContentType.Online, loginFilter, time, views, claims, page);

			return View(model);
		}

		[HttpGet]
		[Authorize(Roles = "Administrator, Moderator")]
		public ViewResult Announcement(string loginFilter, SortDirection? time, SortDirection? views, SortDirection? claims, int? page)
		{
			var model = GetAdminViewModel(OnlineContentType.Announcement, loginFilter, time, views, claims, page);

			return View(model);
		}

		[HttpGet]
		[Authorize(Roles = "Administrator, Moderator")]
		public ViewResult History(string loginFilter, SortDirection? time, SortDirection? views, SortDirection? claims, int? page)
		{
			var model = GetAdminViewModel(OnlineContentType.History, loginFilter, time, views, claims, page);

			return View(model);
		}



        [HttpGet]
        [Authorize(Roles = "Administrator, Moderator, Reports")]
        public ViewResult StatisticReport(DateTime? startDate, DateTime? endDate)
        {
            if (!startDate.HasValue)
            {
                startDate = DateTime.Now.Date.AddDays(-1 * DateTime.Now.Day);
            }
            if (!endDate.HasValue)
            {
                endDate = DateTime.Today.Date.AddDays(1);
            }
            var r = _postingModel.getManyByPeriod(startDate.Value, endDate.Value);
            var model = new  AdminManyStatisticModel
            {
                StartDate = startDate,
                EndDate = endDate,
                inMany=r.inMany,
                outMany = r.outMany,
                sumCurrentMany = r.sumCurrentMany,
                BroadcastPayment = r.BroadcastPayment,
                OnlineContentPayment = r.OnlineContentPayment
            };

            return View(model);
        }










		[HttpGet]
		[Authorize(Roles = "Administrator, Moderator, Reports")]
		public ViewResult FundsReport(DateTime? startDate, DateTime? endDate, SortDirection? money, SortDirection? views, int? page)
		{
			if (!startDate.HasValue && !endDate.HasValue)
			{
				startDate = DateTime.Today.AddDays(-7);
				endDate = DateTime.Today;
			}
			if (!money.HasValue && !views.HasValue)
			{
				views = SortDirection.Descending;
			}

			var model = new AdminFundsViewModel
				{
					StartDate = startDate,
					EndDate = endDate,
					SortByMoney = money,
					SortByViews = views,
					FilterViewModel = new ContentListFilterViewModel
						{
							Action = "FundsReport",
							Controller = "Admin",
							PageNumber = page.HasValue ? page.Value : 1,
							PageSize = 50
						}
				};

			var items = _onlineContentModel.GetAll();

			if (startDate.HasValue)
			{
				items = items.Where(x => x.CreatedTime >= startDate.Value);
			}
			if (endDate.HasValue)
			{
				items = items.Where(x => x.CreatedTime <= endDate.Value);
			}

			model.Items = new List<AdminFundsItemViewModel>(items.Select(x => new AdminFundsItemViewModel
				{
					OnlineContentId = x.Id,
					ImageUrl = x.ImageUrl,
					Money = x.Paids.Sum(y => y.Value),
					Views = x.Views_anonce + x.Views_online + x.Views_history
				}));
			model.TotalMoney = model.Items.Sum(x => x.Money);
			model.TotalViews = model.Items.Sum(x => x.Views);

			if (model.Items.Any())
			{
				if (money.HasValue)
				{
					model.Items = money.Value == SortDirection.Ascending
										 ? model.Items.OrderBy(x => x.Money).ToList()
										 : model.Items.OrderByDescending(x => x.Money).ToList();
				}
				else
				{
					model.Items = views.Value == SortDirection.Ascending
										 ? model.Items.OrderBy(x => x.Views).ToList()
										 : model.Items.OrderByDescending(x => x.Views).ToList();
				}

				var total = model.Items.Count();
				var skip = (model.FilterViewModel.PageNumber - 1) * model.FilterViewModel.PageSize;

				if (skip > total)
				{
					skip = 0;
				}

				model.Items = model.Items.Skip(skip).Take(model.FilterViewModel.PageSize);
				var pageCount = total / model.FilterViewModel.PageSize;

				if (total % model.FilterViewModel.PageSize != 0)
				{
					pageCount = pageCount + 1;
				}

				model.FilterViewModel.PageCount = pageCount;
				model.FilterViewModel.Total = total;
			}

			return View(model);
		}

		[HttpPost]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult Refund(OnlineContentType contentType, int itemId, string loginFilter, SortDirection? time, SortDirection? views, SortDirection? claims)
		{
			_onlineContentModel.Refund(itemId);
			return RedirectToAction(contentType.ToString(), new { loginFilter, time, views, claims });
		}

		[HttpPost]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult UpdateSetting(int id, string value, string description)
		{
			_settingsModel.UpdateSetting(id, value, description);
			System.Web.HttpContext.Current.Application["ShouldUpdateResourceProviderCache"] = true;
			return RedirectToAction("Settings");
		}

		[HttpPost]
		[Authorize(Roles = "Administrator, Moderator")]
		public ExcelResult ExportResources()
		{
			return new ExcelResult("VideoSellerResources.xls", _resourceModel.ExportResources());
		}

		[HttpPost]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult ImportResources(HttpPostedFileBase file)
		{
			if (file != null && file.ContentLength > 0)
			{
				_resourceModel.ImportResources(file.InputStream);
				HttpContext.ApplicationInstance.Dispose();
			}

			return RedirectToAction("Resources");
		}

		[HttpPost]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult LockClient(string login, string loginFilter)
		{
			_clientModel.LockUnlockClient(login, true);
			return RedirectToAction("Clients", new { loginFilter });
		}

		[HttpPost]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult UnlockClient(string login, string loginFilter)
		{
			_clientModel.LockUnlockClient(login, false);
			return RedirectToAction("Clients", new { loginFilter });
		}

		[HttpDelete]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult DeleteClient(Guid userId, string loginFilter)
		{
			_clientModel.DeleteClient(userId, false);
			return RedirectToAction("Clients", new {loginFilter});
		}

		[HttpPost]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult BlockFinance(Guid userId, string loginFilter)
		{
			_financeModel.BlockUnblock(userId, true);
			return RedirectToAction("Finance", new { loginFilter });
		}

		[HttpPost]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult UnblockFinance(Guid userId, string loginFilter)
		{
			_financeModel.BlockUnblock(userId, false);
			return RedirectToAction("Finance", new { loginFilter });
		}

		[HttpPost]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult AddFinance(Guid userIdAdd, string loginFilterAdd, string financeAdd)
		{
			var client = _clientModel.GetClient(userIdAdd);
			_postingModel.AddFinanceOperation(client.Finance, decimal.Parse(financeAdd), FinanceOperation.AdministratorAdd);
			return RedirectToAction("Finance", new { loginFilter = loginFilterAdd });
		}

		[HttpPost]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult SubstractFinance(Guid userIdSubstract, string loginFilterSubstract, string financeSubstract)
		{
			var client = _clientModel.GetClient(userIdSubstract);
			_postingModel.AddFinanceOperation(client.Finance, decimal.Parse(financeSubstract), FinanceOperation.AdministratorSubstract);
			return RedirectToAction("Finance", new { loginFilter = loginFilterSubstract });
		}

		[HttpPost]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult ProcessWithdraw(int postingId, string loginFilter)
		{
			_postingModel.CompleteWithdraw(postingId);
			return RedirectToAction("Withdraw", new { loginFilter });
		}

		[HttpPost]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult PartialProcessWithdraw(int postingId, string loginFilter)
		{
			_postingModel.CompleteNonClaimedWithdraw(postingId);
			return RedirectToAction("Withdraw", new { loginFilter });
		}

		[HttpPost]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult CancelWithdraw(int postingId, string loginFilter, string reason)
		{
			_postingModel.CancelWithdraw(postingId, reason);
			return RedirectToAction("Withdraw", new { loginFilter });
		}

		[HttpDelete]
		[Authorize(Roles = "Administrator, Moderator")]
		public ActionResult DeleteContent(OnlineContentType contentType, int itemId, string loginFilter, SortDirection? time, SortDirection? views, SortDirection? claims)
		{
			_onlineContentModel.DeleteContent(itemId);
			return RedirectToAction(contentType.ToString(), new { loginFilter, time, views, claims });
		}

		[NonAction]
		private AdminOnlineViewModel GetAdminViewModel(OnlineContentType onlineContentType, string loginFilter, SortDirection? time, SortDirection? views, SortDirection? claims, int? page)
		{
			var model = new AdminOnlineViewModel
				{
					ContentType = onlineContentType,
					LoginFilter = loginFilter,
					SortByTime = time,
					SortByViews = views,
					SortByClaims = claims,
					FilterViewModel = new ContentListFilterViewModel
						{
							Action = onlineContentType.ToString(),
							Controller = "Admin",
							PageNumber = page.HasValue ? page.Value : 1,
							PageSize = 50
						}
				};

			if (string.IsNullOrEmpty(loginFilter))
			{
				model.Items = _onlineContentModel.GetAll(onlineContentType).OrderByDescending(x => x.CreatedTime).ToList();
			}
			else
			{
				var user = _membershipUserModel.GetMembershipUser(loginFilter);
				model.Items = new List<OnlineContent>();

				if (user != null)
				{
					model.Items = _onlineContentModel.GetAll(user.UserId, onlineContentType).OrderByDescending(x => x.CreatedTime).ToList();
				}
			}

			if (model.Items.Any())
			{
				if (time.HasValue)
				{
					model.Items = time.Value == SortDirection.Ascending
										 ? model.Items.OrderBy(x => x.CreatedTime).ToList()
										 : model.Items.OrderByDescending(x => x.CreatedTime).ToList();
				}
				else if (claims.HasValue)
				{
					model.Items = claims.Value == SortDirection.Ascending
										 ? model.Items.OrderBy(x => x.Claims).ToList()
										 : model.Items.OrderByDescending(x => x.Claims).ToList();
				}

				var total = model.Items.Count();
				var skip = (model.FilterViewModel.PageNumber - 1) * model.FilterViewModel.PageSize;

				if (skip > total)
				{
					skip = 0;
				}

				model.Items = model.Items.Skip(skip).Take(model.FilterViewModel.PageSize);
				var pageCount = total / model.FilterViewModel.PageSize;

				if (total % model.FilterViewModel.PageSize != 0)
				{
					pageCount = pageCount + 1;
				}

				model.FilterViewModel.PageCount = pageCount;
				model.FilterViewModel.Total = total;
			}

			return model;
		}
	}
}